/*
 * Copyright 2006-2008 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package net.martinimix.bizact.order;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.bluemartini.database.DBUtil;
import com.bluemartini.dna.*;
import com.bluemartini.server.*;
import com.bluemartini.util.AttributeUtil;

public class FinalizeOrder extends BusinessAction {

	private final Log log = LogFactory.getLog(FinalizeOrder.class);
	
	public FinalizeOrder() { }

	public DNAList execute(DNAList dnaIn) throws BMException {
		
		BusinessObject boOrder = dnaIn.removeBusinessObject("ORDER");
		BusinessObjectArray boaPlanShipments = dnaIn.removeBusinessObjectArray("PLAN_SHIPMENT_ARRAY");
		BusinessObjectArray boaOrderLines = dnaIn.removeBusinessObjectArray("ORDER_LINE_ARRAY");
		BusinessObject boOrderEvent = dnaIn.getBusinessObject("ORDER_EVENT");
		BusinessObjectArray boaShoppingCart = dnaIn.removeBusinessObjectArray("CART_ITEM_ARRAY");
		BusinessObject boGeneric = dnaIn.getBusinessObject("GENERIC");
		DNAList dnaInput = new DNAList();
		DNAList dnaResponse = new DNAList();
		DNAList dnaOut = new DNAList();
		DNAList dnaOrderCodes = StatusCodesStartup.getStatusCodes("ORDER");
		DNAList dnaOrderLineCodes = StatusCodesStartup.getStatusCodes("ORDER_LINE");
		String sOrderLineStatusCode = dnaOrderLineCodes.getString("submitted");
		Long orderID = boOrder.getLong("orh_id");
		if(boOrder.getString("status_cd").equals(dnaOrderCodes.getString("saved")) && orderID != null)
		{
			StringBuffer where = new StringBuffer(30);
			where.append("PSL_PSH_ID IN ");
			where.append("(SELECT PSH_ID FROM V_PLAN_SHIP_HEADER WHERE PSH_ORH_ID = ");
			where.append(orderID);
			where.append(")");
			BusinessObjectArray boaDeletePlanShips = DBUtil.selectBusinessObjectArray("PLAN_SHIP_LINE", where.toString(), 0, 0);
			if(boaDeletePlanShips != null)
				DBUtil.deleteBusinessObjectArray(boaDeletePlanShips);
			StringBuffer sWhere = new StringBuffer("PSH_ORH_ID = ");
			sWhere.append(orderID);
			BusinessObjectArray boa = DBUtil.selectBusinessObjectArray("PLAN_SHIPMENT", sWhere.toString(), 0, 0);
			if(boa.size() > 0)
				DBUtil.deleteBusinessObjectArray(boa);
		}
		DNAStringArray validCodes = dnaOrderCodes.getStringArray("orderValid");
		if(validCodes == null)
			validCodes = new DNAStringArray(dnaOrderCodes.getString("paymentSucceeded"));
		if(validCodes.contains(boOrder.getString("status_cd")))
			boOrder.setString("status_cd", dnaOrderCodes.getString("submitted"));
		else
			boOrder.setString("status_cd", dnaOrderCodes.getString("rejected"));
		dnaInput.setBusinessObjectRef("ORDER", boOrder);
		dnaResponse = BMClient.executeBusinessAction("UpdateOrder", dnaInput);
		boOrder = dnaResponse.removeBusinessObject("ORDER");
		AttributeUtil.storeObjectAttributes(boOrder);
		orderID = boOrder.getLongID();
		int iPlanShipmentSize = boaPlanShipments == null ? 0 : boaPlanShipments.size();
		for(int i = 0; i < iPlanShipmentSize; i++)
		{
			BusinessObject boPlanShipment = boaPlanShipments.elementAt(i);
			boPlanShipment.setLong("psh_orh_id", orderID);
			if(boPlanShipment.getLongID() == null)
				boPlanShipment.setBoolean("new", true);
			dnaInput.clear();
			dnaInput.setBusinessObjectRef("PLAN_SHIPMENT", boPlanShipment);
			dnaResponse = BMClient.executeBusinessAction("UpdatePlanShipment", dnaInput);
			BusinessObject boNewPlanShipment = dnaResponse.getBusinessObject("PLAN_SHIPMENT");
			boPlanShipment.merge(boNewPlanShipment);
			boPlanShipment.removeBoolean("new");
			AttributeUtil.storeObjectAttributes(boPlanShipment);
			Integer orderLineIndex = null;
			Long planShipID = boPlanShipment.getLong("psh_id");
			DNAIntegerArray orderLines = boPlanShipment.getIntegerArray("orderLineIndex");
			int sizeLines = orderLines.size();
			
			log.debug("Looping lines based on plan ship index [" + orderLines + "]");
			
			for(int j = 0; j < sizeLines; j++)
			{
				BusinessObject boPlanShipLine = BMContext.createBusinessObject("PLAN_SHIPMENT_LINE");
				orderLineIndex = orderLines.elementAt(j);
				BusinessObject boOrderLine = boaOrderLines.elementAt(orderLineIndex.intValue());
				
				log.debug("Saving order line at index [" + orderLineIndex + "]");
				
				Long orderLineID = saveOrderLine(boOrderLine, orderID, sOrderLineStatusCode);
				boPlanShipLine.setLong("psl_psh_id", planShipID);
				boPlanShipLine.setLong("psl_orl_id", orderLineID);
				boPlanShipLine.setInteger("quantity", boOrderLine.getInteger("quantity"));
				if(boPlanShipLine.getLongID() == null)
					boPlanShipLine.setBoolean("new", true);
				dnaInput.clear();
				dnaInput.setBusinessObjectRef("PLAN_SHIPMENT_LINE", boPlanShipLine);
				dnaResponse = BMClient.executeBusinessAction("UpdatePlanShipLine", dnaInput);
				boPlanShipLine = dnaResponse.getBusinessObject("PLAN_SHIPMENT_LINE");
				boPlanShipLine.removeBoolean("new");
			}

		}

		if(boGeneric != null)
		{
			DNALongArray deletedLines = boGeneric.removeLongArray("deletedLineNumber");
			int iDeleteLineSize = deletedLines == null ? 0 : deletedLines.size();
			if(iDeleteLineSize > 0)
			{
				StringBuffer where = new StringBuffer(100);
				where.append("ORL_ID in (");
				for(int i = 0; i < iDeleteLineSize; i++)
				{
					where.append(deletedLines.elementAt(i));
					where.append(",");
				}

				int len = where.length();
				if(len > 0)
					where.setLength(len - 1);
				where.append(")");
				BusinessObjectArray boaDeleteLines = DBUtil.selectBusinessObjectArray("ORDER_LINE", where.toString(), 0, 0);
				if(boaDeleteLines != null)
					DBUtil.deleteBusinessObjectArray(boaDeleteLines);
				deletedLines.removeAllElements();
			}
		}
		BusinessObject boCartItem = null;
		int iShoppingCartSize = boaShoppingCart == null ? 0 : boaShoppingCart.size();
		for(int i = 0; i < iShoppingCartSize; i++)
		{
			boCartItem = boaShoppingCart.elementAt(i);
			BusinessObject boOrderLine = boaOrderLines.elementAt(i);
			boCartItem.setLong("orderLineID", boOrderLine.getLongID());
		}

		if(boOrderEvent != null)
		{
			boOrderEvent.setLong("orv_orh_id", boOrder.getLong("orh_id"));
			DBUtil.insertBusinessObject(boOrderEvent);
		}
		if(iShoppingCartSize > 0)
		{
			dnaOut.setBusinessObjectArrayRef("CART_ITEM_ARRAY", boaShoppingCart);
			if(boaPlanShipments != null)
				dnaOut.setBusinessObjectArrayRef("PLAN_SHIPMENT_ARRAY", boaPlanShipments);
			dnaOut.setBusinessObjectArrayRef("ORDER_LINE_ARRAY", boaOrderLines);
		}
		dnaOut.setBusinessObjectRef("ORDER", boOrder);
		return dnaOut;
	}

	private Long saveOrderLine(BusinessObject boOrderLine, Long orderID, String sOrderLineStatusCode)
		throws BMException {
		
		if(log.isDebugEnabled()) {
			log.debug("Saving order line with order id [" + orderID + "] " +
					"status [" + sOrderLineStatusCode + "] and line [" + boOrderLine + "]");
		}
		
		Long orderLineID = boOrderLine.getLong("orl_id");
		if(orderLineID == null)
			boOrderLine.setBoolean("new", true);
		boOrderLine.setLong("orl_orh_id", orderID);
		boOrderLine.setString("status_cd", sOrderLineStatusCode);
		DNAList dnaInput = new DNAList();
		dnaInput.setBusinessObjectRef("ORDER_LINE", boOrderLine);
		DNAList dnaResponse = BMClient.executeBusinessAction("UpdateOrderLine", dnaInput);
		BusinessObject boUpdatedOrderLine = dnaResponse.getBusinessObject("ORDER_LINE");
		boOrderLine.removeBoolean("new");
		orderLineID = boUpdatedOrderLine.getLong("orl_id");
		boOrderLine.setLongID(orderLineID);
		BusinessObjectArray boaChildItems = boOrderLine.getBusinessObjectArray("childLineItems");
		if(boaChildItems != null)
		{
			int i = 0;
			for(int size = boaChildItems.size(); i < size; i++)
			{
				BusinessObject boChildItem = boaChildItems.elementAt(i);
				boChildItem.setLong("orl_parent_id", orderLineID);
				saveOrderLine(boChildItem, orderID, sOrderLineStatusCode);
			}

		}
		return orderLineID;
	}
}
